package com.gopay.cron.service.trans.impl;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.gopay.common.PageInfo;
import com.gopay.common.constants.txncd.IntTxnCd;
import com.gopay.common.cps.dao.order.CpsGeneralMainOrderQueryDAO;
import com.gopay.common.cps.dao.order.CpsGeneralPayOrderQueryDAO;
import com.gopay.common.datasource.DBType;
import com.gopay.common.datasource.DbContextHolder;
import com.gopay.common.domain.cps.CpsGenMainOrder;
import com.gopay.common.domain.report.Event;
import com.gopay.common.domain.report.ReportConsoleTransQuery;
import com.gopay.common.event.EventState;
import com.gopay.common.event.ReportEventType;
import com.gopay.common.exception.GopayException;
import com.gopay.common.order.dao.CommonQueryDAO;
import com.gopay.common.report.dao.MqEventInfoDAO;
import com.gopay.common.report.dao.ReportConsoleTransQueryDAO;
import com.gopay.cron.service.trans.ReportConsoleTransQueryService;
import com.gopay.cron.service.trans.TransQueryService;
import com.gopay.cron.web.vo.TransQueryParamVO;
import com.gopay.cron.web.vo.TransQueryResultVO;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import org.apache.commons.lang.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.*;

@Service(value = "reportConsoleTransQueryService")
public class ReportConsoleTransQueryServiceImpl implements ReportConsoleTransQueryService {
    @Resource(name = "reportConsoleTransQueryDAO")
    private ReportConsoleTransQueryDAO reportConsoleTransQueryDAO;

    
    @Resource(name="commonQueryDAO")
    protected CommonQueryDAO commonQueryDAO;
    
    @Resource
    private TransQueryService transQueryService;
    
    @Resource(name = "mqEventInfoDAO")
    private MqEventInfoDAO mqEventInfoDAO;
    @Resource(name = "cpsGenPayOrderQueryDAO")
    private CpsGeneralPayOrderQueryDAO cpsGenPayOrderQueryDAO;

    @Resource(name = "cpsGeneralMainOrderQueryDAO")
    private CpsGeneralMainOrderQueryDAO cpsGeneralMainOrderQueryDAO;
    private Logger log = LoggerFactory.getLogger(ReportConsoleTransQueryServiceImpl.class);

    @Autowired
    private CacheManager cacheManager ;
    private static final byte[] LOCK = new byte[0];
    @Override
    public void saveOrUpdateTransQueryResultList(List<TransQueryResultVO> list) {
        for (TransQueryResultVO t : list) {
            try {
                saveOrUpdateResult(t);
            } catch (Exception e) {
                //出现异常则重试一次 lx  生产bug7期 2017-8-1 08:54:09
                //e.printStackTrace();
                saveOrUpdateResult(t);
            }
        }
    }

    private void saveOrUpdateResult(TransQueryResultVO t) {
        ReportConsoleTransQuery result = reportConsoleTransQueryDAO.find(ReportConsoleTransQuery.class, t.getGopayOrderId());
        if (null != result ) {
            this.updateTransQueryResult(t);
        } else {
            synchronized (LOCK){//同步缓存 判断是否有当前订单
                Cache cache = cacheManager.getCache("insertOrderCacheConfig");
                Element element = cache.get(t.getGopayOrderId());
                if (element == null) {//只有缓存中为空的时候 才进行插入操作 防止主键冲突
                    cache.put(new Element(t.getGopayOrderId(),t.getGopayOrderId()));
                    log.info("===========cronReal saveOrUpdate Insert ======"+t.getGopayOrderId());
                }else{//不为空说明订单已经进行save操作
                    return ;
                }
            }
            this.saveTransQueryResult(t);
        }
    }


    private void saveTransQueryResult(TransQueryResultVO t) {
        long startTime = System.currentTimeMillis();
        ReportConsoleTransQuery r = new ReportConsoleTransQuery();
        r.setGopayOrderId(t.getGopayOrderId());
        String tranFinishTime = t.getTranFinishTime();
        if (null != tranFinishTime && !"".equals(tranFinishTime)) {
            Timestamp gopaytxnTm = Timestamp.valueOf(tranFinishTime);
            r.setGopayTxnTm(gopaytxnTm);
        }else{
            r.setGopayTxnTm(null);
        }
        
        String orderStlmTime = t.getOrderStlmTime();
        if (null != orderStlmTime && !"".equals(orderStlmTime)) {
            Timestamp orderStlmTimeDate = Timestamp.valueOf(orderStlmTime);
            r.setOrderStlmTm(orderStlmTimeDate);
        }else{
            r.setOrderStlmTm(null);
        }
        r.setCustOrderId(t.getMerOrderId());
        r.setTxnPlace(t.getTransAdr());
        r.setPayCustName(t.getPayCustName());
        r.setTxnAmt(null == t.getOrderDealAmt()?new BigDecimal(0):new BigDecimal(t.getOrderDealAmt()));
        r.setRealFeeAmt(null == t.getOrderRealFeeAmt()?new BigDecimal(0):new BigDecimal(t.getOrderRealFeeAmt()));
        r.setRefundFeeAmt(null == t.getRefundFeeAmt()?new BigDecimal(0):new BigDecimal(t.getRefundFeeAmt()));
        r.setPayBankName(t.getMainPayAcct());
        r.setRecvBankName(t.getMainRecvAcctProdName());
        r.setRecvBankOrderId(t.getGopayOutOrderId());
        r.setPayCustEmail(t.getPayCusEmail());
        r.setPayAcct(t.getPayAcct());
        r.setRecvCustName(t.getRecCusName());
        r.setRecvCustEmail(t.getRecCusMail());
        r.setRecvAcct(t.getMainRecvAcct());
        r.setPayAcctProdCd(t.getAcctType());
        r.setGopayIntTxnCd(t.getTransTypeId());
        r.setPayChannel(t.getPayChannel());
        r.setTxnStaCd(null == t.getTransStatusId()?0:Integer.valueOf(t.getTransStatusId()));
        r.setSettleType(t.getPayType());
        r.setTerminalSource(getPaySource(t.getPaySource()));

        r.setHandleStaCd(getHanderStatus(t.getHanderStatus()));
        //update by dongdh 20160616 鉴权交易将关联订单号存在主订单表remark1, 这里未同步到报表库
        if("自动提现".equals(t.getRemark1()) || IntTxnCd._00603.value.equals(t.getTransTypeId())){
            r.setRemark(t.getRemark1());
        }
        r.setUserSource(t.getUserSource());
        r.setTotalOrderAmt(null == t.getTotalOrderAmt()?new BigDecimal(0):new BigDecimal(t.getTotalOrderAmt()));
        Date now = new Date();
        r.setCreatedTs(now);
        r.setLastUpdTs(now);
        //金额修改-增加结算金额和手续费承担方字段-jiaoshuai
        r.setOrderFeePayer(t.getOrderFeePayer());
        r.setSettleAmt(null == t.getSettleAmt()?new BigDecimal(0):new BigDecimal(t.getSettleAmt()));
        //视频会员卡 备注字段要显示直充账号 add by zhoupeng 20170630 
        if(IntTxnCd._01618.value.equals(t.getTransTypeId()) &&StringUtils.isNotBlank(t.getRemark1())){
        	r.setRemark(t.getRemark1().split("_").length==2?t.getRemark1().split("_")[1]:"");
        }
        r.setOldPayChannel(addOldPayChannelInfoToOptimizedTransQueryVO(t.getGopayOrderId()));
        long startTime1 = System.currentTimeMillis();
        reportConsoleTransQueryDAO.save(r);
        log.info("组装对象耗时[{}],save耗时[{}]", startTime1 - startTime, System.currentTimeMillis() - startTime1);
    }

    

    @Override
    public void deleteByGoPayOrderId(String gopayOrderId) {
        StringBuilder deleteSql = new StringBuilder();
        deleteSql.append("DELETE ");
        deleteSql.append("FROM report_console_trans_query r ");
        deleteSql.append("WHERE r.gopay_order_id = :gopayOrderId");

        Map<String, Object> map = new HashMap<String, Object>();
        map.put("gopayOrderId", gopayOrderId);

        reportConsoleTransQueryDAO.updateBySql(deleteSql.toString(), map);
    }

    @Override
    public List<TransQueryResultVO> getTransQueryResultList(Map<String, Object> map) throws GopayException {
        String gopayOrderId = (String) map.get("gopayOrderId");
        // CpsGenMainOrder mainOrder = (CpsGenMainOrder) map.get("mainOrder");
        PageInfo pageInfo = new PageInfo();
        TransQueryParamVO paramVo = new TransQueryParamVO();
        paramVo.setChangeNum(gopayOrderId);
        return transQueryService.query(paramVo, pageInfo);
    }
    
  
    
    public boolean updateTransQueryResult(TransQueryResultVO t) {
        ReportConsoleTransQuery r = reportConsoleTransQueryDAO.find(ReportConsoleTransQuery.class, t.getGopayOrderId());
        if(null == r){
           
            return false;
        }
        
        String tranFinishTime = t.getTranFinishTime();
        if (null != tranFinishTime && !"".equals(tranFinishTime)) {
            Timestamp gopaytxnTm = Timestamp.valueOf(tranFinishTime);
            r.setGopayTxnTm(gopaytxnTm);
        }else{
            r.setGopayTxnTm(null);
        }
        
        String orderStlmTime = t.getOrderStlmTime();
        if (null != orderStlmTime && !"".equals(orderStlmTime)) {
            Timestamp orderStlmTimeDate = Timestamp.valueOf(orderStlmTime);
            r.setOrderStlmTm(orderStlmTimeDate);
        }else{
            r.setOrderStlmTm(null);
        }

        r.setTxnPlace(t.getTransAdr());
        r.setPayCustName(t.getPayCustName());
        r.setPayBankName(t.getMainPayAcct());
        r.setRecvBankOrderId(t.getGopayOutOrderId());
        r.setPayCustEmail(t.getPayCusEmail());
        r.setPayAcct(t.getPayAcct());
        r.setRecvCustName(t.getRecCusName());
        r.setRecvCustEmail(t.getRecCusMail());
        r.setPayAcctProdCd(t.getAcctType());
        r.setPayChannel(t.getPayChannel());
        r.setTxnStaCd(null == t.getTransStatusId()?0:Integer.valueOf(t.getTransStatusId()));
        r.setSettleType(t.getPayType());
        r.setTerminalSource(getPaySource(t.getPaySource()));
        r.setRealFeeAmt(null == t.getOrderRealFeeAmt()?new BigDecimal(0):new BigDecimal(t.getOrderRealFeeAmt()));
        r.setRefundFeeAmt(null == t.getRefundFeeAmt()?new BigDecimal(0):new BigDecimal(t.getRefundFeeAmt()));
        r.setTxnAmt(null == t.getOrderDealAmt()?new BigDecimal(0):new BigDecimal(t.getOrderDealAmt()));
        r.setRecvBankName(t.getMainRecvAcctProdName());
        r.setHandleStaCd(getHanderStatus(t.getHanderStatus()));
        r.setLastUpdTs(new Date());
        
      //update by dongdh 20160616 鉴权交易将关联订单号存在主订单表remark1, 这里未同步到报表库
        if("自动提现".equals(t.getRemark1()) || IntTxnCd._00603.value.equals(t.getTransTypeId())){
            r.setRemark(t.getRemark1());
        }
        r.setUserSource(t.getUserSource());
        r.setTotalOrderAmt(null == t.getTotalOrderAmt()?new BigDecimal(0):new BigDecimal(t.getTotalOrderAmt()));
        //金额修改-增加结算金额和手续费承担方字段-jiaoshuai
        r.setOrderFeePayer(t.getOrderFeePayer());
        r.setSettleAmt(null == t.getSettleAmt()?new BigDecimal(0):new BigDecimal(t.getSettleAmt()));
        //视频会员卡 备注字段要显示直充账号 add by zhoupeng 20170630 
        if(IntTxnCd._01618.value.equals(t.getTransTypeId()) && StringUtils.isNotBlank(t.getRemark1())){
        	r.setRemark(t.getRemark1().split("_").length==2?t.getRemark1().split("_")[1]:"");
        }
        r.setOldPayChannel(addOldPayChannelInfoToOptimizedTransQueryVO(t.getGopayOrderId()));
        reportConsoleTransQueryDAO.update(r);
        return true;
    }

   
    
   

    private String getHanderStatus(String handerStatus) {
        return "处理中".equals(handerStatus) ? "01" : "待审核".equals(handerStatus) ? "02"
                : "待确认".equals(handerStatus) ? "03" : "成功".equals(handerStatus) ? "04" : "失败".equals(handerStatus)?"05":"";
    }


    

//    private String getPaySource(String paySource) {
//        return "PC端".equals(paySource) ? "01" : "移动端".equals(paySource) ? "02"
//                : "";
//    }
    
    private String getPaySource(String paySource) {
    	return paySource;
//        return "PC端".equals(paySource) ? "01" : "移动端".equals(paySource) ? "02"
//                : "APP端";
    }


    /**
     * 更新缓存表订单信息
     */
    @Override
    public void processInitialOrder(String ymd) {
        DbContextHolder.setDbType(DBType.DS_REPORT.value);
        log.info("开始查询缓存表进行中且事件流水表为处理成功或失败的订单");
        List<Object> goPayOrderIdList = reportConsoleTransQueryDAO.findInitialOrderBySql(ymd);
        
        log.info("查询缓存表进行中且事件流水表为处理成功或失败的订单结束 processOrderList.size()=" + goPayOrderIdList.size() );
        if(null == goPayOrderIdList || goPayOrderIdList.size() < 1){
            return ;
        }
        
        TransQueryParamVO paramVo = new TransQueryParamVO();
        PageInfo pageInfo = new PageInfo();
        log.info("开始处理订单");
        for (Object o : goPayOrderIdList) {
            paramVo.setChangeNum((String) o);
            try {
                List<TransQueryResultVO> result = transQueryService.query(paramVo, pageInfo);
                DbContextHolder.setDbType(DBType.DS_REPORT.value);
                if(null != result && result.size() > 0){
                    for (TransQueryResultVO t : result) {
                        this.updateTransQueryResult(t);
                    }
                }
            } catch (GopayException e) {
               log.error("查询老交易订单出错", e);
            }
        }
        log.info("处理订单结束");
    }

    /**
     * 补全缓存表中订单信息
     */
    @Override
    public void completeReportOrder(String ymd) {
        DbContextHolder.setDbType(DBType.DS_ONLY_READ.value);
        String oldQueryGopayOrderIdSql = " select m.gopay_order_id from cps_gen_main_order m";
        oldQueryGopayOrderIdSql += " where 1 = 1";
        oldQueryGopayOrderIdSql += " and ((m.gopay_int_txn_cd = '01302' and";
        oldQueryGopayOrderIdSql += " m.relevance_gopay_order_id is null) or";
        oldQueryGopayOrderIdSql += " m.gopay_int_txn_cd <> '01302')";
        Date now = new Date();
        oldQueryGopayOrderIdSql += " and m.gopay_order_id like '" + ymd + "%'";
        List<Object[]> oldQueryGopayOrderIdList = commonQueryDAO.findBySql(oldQueryGopayOrderIdSql);
        DbContextHolder.setDbType(DBType.DS_REPORT.value);
        List<Object> newQueryGopayOrderIdList = reportConsoleTransQueryDAO.findLackOrderBySql(ymd);

        List<Event> toSaveEventList = new ArrayList<Event>();
        Set<String> newQueryGopayOrderIdSet = new HashSet<String>();
        for (Object o : newQueryGopayOrderIdList) {
            newQueryGopayOrderIdSet.add((String) o);
        }
        for (Object o : oldQueryGopayOrderIdList) {
            String goPayOrderId = (String) o;
            if (newQueryGopayOrderIdSet.add(goPayOrderId)) {
                Event e = new Event();
                e.setGopayOrderId(goPayOrderId);
                e.setCreatedTs(now);
                e.setLastUpdTs(now);
                e.setType(ReportEventType.ORDER_SAVE.value);
                e.setStat(EventState.PROGRESS.value);
                toSaveEventList.add(e);
            }
        }

        if (null != toSaveEventList && toSaveEventList.size() > 0) {
            log.info("共有" + toSaveEventList.size() + "条记录需要补全");
            mqEventInfoDAO.batchSave(toSaveEventList);
        }

    }

    private String addOldPayChannelInfoToOptimizedTransQueryVO(String gopayOrderId){
        CpsGenMainOrder mainOrder = cpsGeneralMainOrderQueryDAO.findByGopayOrderId(gopayOrderId);
        if(StringUtils.isNotBlank(mainOrder.getRelevanceGopayOrderId())){
            CpsGenMainOrder oldMainOrder = cpsGeneralMainOrderQueryDAO.findByGopayOrderId(mainOrder.getRelevanceGopayOrderId());
            return oldMainOrder.getPayChannel();
        }
        return "";
    }

}
